/*****************************************************************************
*                     Organizacion de Datos - 75.06                          *
*                         Catedra Lic. Servetto                              *
*            Facultad de Ingenieria - Universidad de Buenos Aires            *
******************************************************************************/

#include "ConexionCapaIndices.h"

#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

using namespace std;
using namespace Comun;

namespace CapaMetadata
{
	static int contadorOperaciones = 0;

	void ConexionCapaIndices::EjecutarLlamada(stringstream* entrada, stringstream* salida)
	{
		if (contadorOperaciones < 0)
			contadorOperaciones = 0;

		stringstream* s = new stringstream();
		*s << "Transacciones/CapaIndices/Entrada/" << contadorOperaciones << ".txt";

		ofstream archivoEntrada(s->str().c_str());
		archivoEntrada << salida->rdbuf();
		archivoEntrada.close();

#ifdef WIN32
		s = new stringstream();
		*s << "CapaIndices.EXE " << contadorOperaciones;

		system(s->str().c_str());
#else

		s = new stringstream();
		*s << "./CapaIndices " << contadorOperaciones;

		system(s->str().c_str());
#endif

		s = new stringstream();
		*s << "Transacciones/CapaIndices/Salida/" << contadorOperaciones << ".txt";

		ifstream* archivoSalida = new ifstream();
		
		archivoSalida->open(s->str().c_str());

		(*entrada) << archivoSalida->rdbuf();

		archivoSalida->close();
		delete archivoSalida;

		contadorOperaciones++;
	}

	stringstream* ConexionCapaIndices::ArchIndicesExisteClase(std::string NombreClase){
		return EncabezadoArchIndices(NombreClase,"ExisteClase");
	}

	stringstream* ConexionCapaIndices::ArchIndicesAltaClase(std::string PathCreacionClase){
		stringstream* Arch = new stringstream();
		fstream DefClase(PathCreacionClase.c_str());
		
		string str;
		while (getline(DefClase,str)){
			*Arch << str << endl;
		}
		DefClase.close();
		return Arch;
	}

	stringstream* ConexionCapaIndices::ArchIndicesGetMetadataClase(std::string NombreClase){
		return EncabezadoArchIndices(NombreClase,"GetMetadataClase");
	}

	stringstream* ConexionCapaIndices::ArchIndicesInsercion(std::string NombreClase,list<ClaveValor>* Valores){
		stringstream* Arch=EncabezadoArchIndices(NombreClase,"Insercion");

		*Arch << "[Datos]" << endl;
		for (list<ClaveValor>::iterator it=Valores->begin();it!=Valores->end();++it){
			ClaveValor& CV=*it;
			*Arch << "[Dato]" << endl;
			*Arch << "Atributo = " << CV.Clave << endl;
			*Arch << "Valor = " << CV.Valor << endl;
		}
		return Arch;
	}

	stringstream* ConexionCapaIndices::ArchIndicesBorrado(std::string NombreClase,CondicionCompuesta* Cond){
		stringstream* Arch=EncabezadoArchIndices(NombreClase,"Borrado");
		/*
	[Condiciones]
	Tipo = AND
	  [Condicion]
		Atributo = NombreDeAtributo
		Operador = >=
		Valor = valorAComparar
	  [Condicion]
		Atributo = NombreDeAtributo
		Operador = >=
		Valor = valorAComparar
	*/

		*Arch << "[Condiciones]" << endl;
		if (Cond->EsAnd()){
			*Arch << "Tipo = AND" << endl;
		}else{
			*Arch << "Tipo = AND" << endl;
		}
		for (list<Condicion*>::iterator it=Cond->Subcondiciones.begin();it!=Cond->Subcondiciones.end();++it){
			Condicion* Cnd=*it;
			
			*Arch << "[Condicion]" << endl;
			*Arch << "Atributo = " << Cnd->ValorCondicion.Nombre << endl;
			*Arch << "Operador = " << Cnd->getSimbolo() << endl;
			*Arch << "Valor = " << Cnd->ValorCondicion.Valor << endl;
		}
		return Arch;
	}

	stringstream* ConexionCapaIndices::ArchIndicesSeleccion(std::string NombreClase,CondicionCompuesta* Cond,list<string>* Campos){
		stringstream* Arch=EncabezadoArchIndices(NombreClase,"Seleccion");
		/*
	[Condiciones]
	Tipo = AND
	  [Condicion]
		Atributo = NombreDeAtributo
		Operador = >=
		Valor = valorAComparar
	  [Condicion]
		Atributo = NombreDeAtributo
		Operador = >=
		Valor = valorAComparar

	[CamposSeleccion]
	  Atributo = Nombre
	  Atributo = Id

	*/

		*Arch << "[Condiciones]" << endl;
		if (Cond->EsAnd()){
			*Arch << "Tipo = AND" << endl;
		}else{
			*Arch << "Tipo = OR" << endl;
		}
		for (list<Condicion*>::iterator it=Cond->Subcondiciones.begin();it!=Cond->Subcondiciones.end();++it){
			Condicion* Cnd=*it;
			
			*Arch << "[Condicion]" << endl;
			*Arch << "Atributo = " << Cnd->ValorCondicion.Nombre << endl;
			*Arch << "Operador = " << Cnd->getSimbolo() << endl;
			*Arch << "Valor = " << Cnd->ValorCondicion.Valor << endl;
		}

		*Arch << endl <<"[CamposSeleccion]" << endl;
		for (list<string>::iterator it=Campos->begin();it!=Campos->end();++it){
			*Arch << "Atributo = " << *it << endl;
		}


		return Arch;
	}

	stringstream* ConexionCapaIndices::ArchIndicesActualizacion(std::string NombreClase,list<ClaveValor>* Valores,CondicionCompuesta* Cond){
		stringstream* Arch=EncabezadoArchIndices(NombreClase,"Actualizacion");

		*Arch << "[Condiciones]" << endl;
		if (Cond->EsAnd()){
			*Arch << "Tipo = AND" << endl;
		}else{
			*Arch << "Tipo = AND" << endl;
		}
		for (list<Condicion*>::iterator it=Cond->Subcondiciones.begin();it!=Cond->Subcondiciones.end();++it){
			Condicion* Cnd=*it;
			
			*Arch << "[Condicion]" << endl;
			*Arch << "Atributo = " << Cnd->ValorCondicion.Nombre << endl;
			*Arch << "Operador = " << Cnd->getSimbolo() << endl;
			*Arch << "Valor = " << Cnd->ValorCondicion.Valor << endl;
		}

		*Arch << endl <<"[Datos]" << endl;
		for (list<ClaveValor>::iterator it=Valores->begin();it!=Valores->end();++it){
			ClaveValor& CV=*it;
			*Arch << "[Dato]" << endl;
			*Arch << "Atributo = " << CV.Clave << endl;
			*Arch << "Valor = " << CV.Valor << endl;
		}
	

		
		return Arch;
	}

	stringstream* ConexionCapaIndices::EncabezadoArchIndices(std::string NombreClase,std::string Operacion){
		stringstream* result=new stringstream;
		*result << "[Operacion]" << endl;
		*result << "Nombre = " << Operacion << endl;
		*result << "Clase = " << NombreClase << endl << endl;
		return result;
	}
	
	list<Registro>* ConexionCapaIndices::LeerRegistros(std::string NombreArch,list<string>* Columnas)
	{
		ifstream archivo(NombreArch.c_str(),ios::out);
		string line;	
		list<Registro>* buffer=new list<Registro>;
		//leo una vez para obviar la cabecera
		getline(archivo,line);

		while(getline(archivo,line)){
			
			Registro* r = new Registro();

			int j = 0;
			list<string>::iterator it = Columnas->begin();

			while(j < line.size() )
			{
				Atributo* a = new Atributo();
				a->Nombre = *it;

				while ((line[j] != ';') && (j < line.size()))			
					a->Valor += line[j++];		

				j++;
				it++;
				r->Atributos.push_back(*a);				
			}

			buffer->push_back(*r);		

		}
		archivo.close();
		return buffer;
	}

	bool ConexionCapaIndices::LeerRegistrosBuffer(ifstream* archivo,list<Registro>* buffer,list<string>* Columnas)	
	{
		buffer->clear(); //vacio el buffer
		string line;	

		for (int i = 0; i< 10; i++)		
		{
			if(!getline(*archivo,line))
				return false;

			Registro* r = new Registro();

			int j = 0;
			list<string>::iterator it = Columnas->begin();

			while(j < line.size() )
			{
				Atributo* a = new Atributo();
				a->Nombre = *it;

				while ((line[j] != ';') && (j < line.size()))			
					a->Valor += line[j++];		

				j++;
				it++;
				r->Atributos.push_back(*a);				
			}

			buffer->push_back(*r);		

		}

		return true;
	}
}
